from typing import List

from sqlalchemy import Enum, ForeignKey, Integer, JSON, String
from sqlalchemy.orm import Mapped, mapped_column, relationship

from ._basic_ import BasicModel
from ._secondary_tables_ import conversation_ai_model_association


# noinspection SpellCheckingInspection
class AIProvider(Enum):
    """
    AI 供应商枚举类
    """
    OPENAI = 'openai'
    """
    OpenAI
    """
    IFLYTEK = 'iflytek'
    """
    科大讯飞
    """


class AIModelType(Enum):
    """
    AI 模型类型
    """
    CHAT = 'chat'
    """
    对话模型
    """
    CHAT_WITH_VISION = 'chat-with-vision'
    """
    具有视觉能力的对话模型
    """


class AIInstance(BasicModel):
    """
    AI 实例
    通常代表不同的 AI 供应商给出的接口实例
    """
    __tablename__ = 'ai_instances'

    name: Mapped[str] = mapped_column(String(255), unique=True, index=True, nullable=False, comment='实例名称')
    """
    AI 实例名称
    """
    provider: Mapped[AIProvider] = mapped_column(AIProvider, nullable=False, comment='供应商类型')
    """
    AI 供应商类型
    """
    app_id: Mapped[str] = mapped_column(String(255), nullable=True, comment='应用 ID')
    """
    应用 ID
    将作为部分 AI 供应商接口参数
    """
    api_key: Mapped[str] = mapped_column(String(255), nullable=True, comment='API 访问密钥')
    """
    API 访问密钥
    将作为部分 AI 供应商接口参数
    """
    api_secret: Mapped[str] = mapped_column(String(255), nullable=True, comment='API 安全密钥')
    """
    API 安全密钥
    将作为部分 AI 供应商接口参数
    """
    instance_params: Mapped[dict] = mapped_column(JSON, nullable=True, comment='实例参数')
    """
    实例参数
    将作为 AI 实例中的自定义参数
    """
    models: 'Mapped[List[AIModel]]' = relationship('AIModel', back_populates='instance', cascade='all')


class AIModel(BasicModel):
    """
    AI 模型
    通常代表同一个 AI 实例下的不同 AI 模型
    """
    __tablename__ = 'ai_models'

    instance: Mapped[AIInstance] = relationship('AIInstance', back_populates='models', cascade='all')
    """
    实例
    """
    instance_id: Mapped[int] = mapped_column(Integer, ForeignKey('ai_instances.id'), comment='实例 ID')
    """
    实例 ID
    """

    name: Mapped[str] = mapped_column(String(255), unique=True, index=True, nullable=False, comment='模型显示名称')
    """
    模型显示名称
    用于前端展示
    """
    model_type: Mapped[AIModelType] = mapped_column(AIModelType, nullable=False, comment='模型类型')
    """
    模型类型
    """
    model_name: Mapped[str] = mapped_column(String(255), nullable=False, comment='模型名称')
    """
    模型名称
    将作为 AI 接口中的模型名称参数
    """
    model_version: Mapped[str] = mapped_column(String(255), nullable=False, comment='模型版本')
    """
    模型版本
    将作为 AI 接口中的模型版本参数
    """
    model_params: Mapped[dict] = mapped_column(JSON, nullable=True, comment='模型参数')
    """
    模型参数
    将作为 AI 接口中的自定义参数
    """
    max_tokens: Mapped[int] = mapped_column(Integer, nullable=True, comment='最大令牌数')
    """
    最大令牌数
    限制允许模型响应内容的最大令牌数
    注意：最大令牌数 != 最大文本长度
    """

    identities = relationship('AIIdentity', back_populates='model')
    """
    关联的 AI 身份列表
    """
    conversations = relationship(
        'Conversation',
        secondary=conversation_ai_model_association,
        back_populates='ai_models',
    )
    """
    关联的对话列表
    """
